#include "nvs_operator.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "esp_system.h"
nvs_handle_t handle = NULL;
#define TAG "nvs-operator"
void nvs_op_init()
{
    // Initialize NVS
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        // NVS partition was truncated and needs to be erased
        // Retry nvs_flash_init
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);
    err = nvs_open("storage", NVS_READWRITE, &handle);
}
typedef union data_shared
{
    uint32_t i;
    float f;
} u_data_shared;

static u_data_shared u_data;

void nvs_op_get_float_value(const char *key, float *value, float default_value)
{
    ESP_LOGI(TAG, "get value: %s :%f", key, default_value);
    uint32_t tmp = 0;
    esp_err_t err;
    err = nvs_get_u32(handle, key, &tmp);
    if (err != ESP_OK)
    {
        *value = default_value;
        nvs_op_set_float_value(key, default_value);

        return;
    }
    u_data.i = tmp;
    *value = u_data.f;
}
void nvs_op_set_float_value(const char *key, float value)
{
    ESP_LOGI(TAG, "set value: %s :%f", key, value);
    esp_err_t err;
    u_data.f = value;
    err = nvs_set_u32(handle, key, u_data.i);
    err = nvs_commit(handle);
}

void nvs_op_get_int32_value(const char *key, int32_t *value, int32_t default_value)
{
    ESP_LOGI(TAG, "get value: %s :%d", key, default_value);
    int32_t tmp = 0;
    esp_err_t err;
    err = nvs_get_i32(handle, key, &tmp);
    if (err != ESP_OK)
    {
        *value = default_value;
        nvs_op_set_int32_value(key, default_value);
        return;
    }
    *value = tmp;
}
void nvs_op_set_int32_value(const char *key, int32_t value)
{
    ESP_LOGI(TAG, "set value: %s :%d", key, value);
    esp_err_t err;
    err = nvs_set_i32(handle, key, value);
    err = nvs_commit(handle);
}
void nvs_op_get_u32_value(const char *key, uint32_t *value, uint32_t default_value)
{
    ESP_LOGI(TAG, "get value: %s :%u", key, default_value);
    uint32_t tmp = 0;
    esp_err_t err;
    err = nvs_get_u32(handle, key, &tmp);
    if (err != ESP_OK)
    {
        *value = default_value;
        nvs_op_set_u32_value(key, default_value);
        return;
    }
    ESP_LOGI(TAG, " value:%u", tmp);
    *value = tmp;
}
void nvs_op_set_u32_value(const char *key, uint32_t value)
{
    ESP_LOGI(TAG, "set value: %s :%u", key, value);
    esp_err_t err;
    err = nvs_set_u32(handle, key, value);
    err = nvs_commit(handle);
}

void nvs_op_get_string(const char *key, char *str, int16_t size, char *default_str)
{
    size_t required_size;
    esp_err_t err;
    memset(str, 0, sizeof(size));
    err = nvs_get_str(handle, key, NULL, &required_size);
    if (err != ESP_OK)
    {
        strcpy(str, default_str);
        return;
    }
    char *value = malloc(required_size);
    err = nvs_get_str(handle, key, value, &required_size);
    if (err != ESP_OK)
    {
        strcpy(str, default_str);
        free(value);
        return;
    }

    strcpy(str, value);
    free(value);
}
void nvs_op_set_string(const char *key, char *str, int16_t size)
{
    esp_err_t err;
    err = nvs_set_str(handle, key, str);
    err = nvs_commit(handle);
}